﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using Dapper;
using BCCommon.OAEnums;
using BCEntity.OA.Attendance.AttendanceRemedyApply;
using BCEntity.OA.TeamWorks.TaskRecord;
using BCEntity.OA.Workflow.WorkflowActivityInstanceReference;
using BCCommon;
namespace BCData.OA.TeamWorks.AttendanceTaskRecord
{
    public class AttendanceTaskRecordData : IAttendanceTaskRecordData
    {
        private readonly IDatabaseContext databaseContext;
        private const string QUERY = @"SELECT TaskRecordNo,BusinessTypeName,BusinessType,WorkflowActivityInstanceId,
                                            TaskCategory,HandleStatus,PauseTime,PauseRemark,RelevantTaskRecordNo,CurrentlyStep,CreateTime,TaskExecuterAdminId,
                                            TaskExecuterFullName,StartTime,CompleteTime
                                        FROM OA_TaskRecord";

        public AttendanceTaskRecordData(IDatabaseContext databaseContext)
        {
            this.databaseContext=databaseContext;
        }


        /// <summary>
        /// 新增一组任务列表
        /// </summary>
        /// <param name="mainTaskRecordNo">主线任务编号</param>
        /// <param name="entities">任务列表</param>
        /// <param name="receiverEntities">任务抄送人信息</param>
        /// <param name="referenceEntity">任务相关业务</param>
        /// <returns></returns>
        public async Task<IEnumerable<TaskRecordEntity>> InsertListAsync(AttendanceRemedyApplyEntity remedyApplyEntity, List<TaskRecordEntity> entities, List<TaskReceiverRecordEntity> receiverEntities = null, WorkflowActivityInstanceReferenceEntity referenceEntity = null)
        {
            List<string> sqls = new List<string>();
            List<DynamicParameters> parametersList = new List<DynamicParameters>();
            sqls.AddRange(this.GetInsertTaskRecordListSql(entities, receiverEntities, referenceEntity, remedyApplyEntity, ref parametersList));
            int result = this.databaseContext.Master.TransactionExecuteAsync(sqls, parametersList, databaseContext.Transaction).GetAwaiter().GetResult();
            if (result > 0)
            {
                return await this.Get(entities.First().WorkflowActivityInstanceId);
            }
            return new List<TaskRecordEntity>();
        }

        public async Task<IEnumerable<TaskRecordEntity>> Get(long workflowActivityInstanceId)
        {
            string sql = string.Format("{0} WHERE WorkflowActivityInstanceId=?WorkflowActivityInstanceId", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WorkflowActivityInstanceId", workflowActivityInstanceId, DbType.Int64, size: 20);
            return await this.databaseContext.Slave.QueryAsync<TaskRecordEntity>(sql, parameters);
        }


        private IEnumerable<string> GetInsertTaskRecordListSql(List<TaskRecordEntity> entities, List<TaskReceiverRecordEntity> receiverEntities, WorkflowActivityInstanceReferenceEntity referenceEntity, AttendanceRemedyApplyEntity remedyApplyEntity, ref List<DynamicParameters> parametersList)
        {
            List<string> sqls = new List<string>();

            DynamicParameters parameters1 = new DynamicParameters();
            sqls.Add(this.GetInsertAttendanceRemedyApplySql(remedyApplyEntity, out parameters1));
            parametersList.Add(parameters1);

            foreach (var item in entities)
            {
                DynamicParameters parameters = new DynamicParameters();
                sqls.Add(this.GetInsertTaskRecordSql(item, out parameters));
                parametersList.Add(parameters);
            }
            if (receiverEntities != null && receiverEntities.Any())
            {
                foreach (var receiver in receiverEntities)
                {
                    DynamicParameters parameters = new DynamicParameters();
                    sqls.Add(this.GetInsertTaskReceiverRecordSql(receiver, out parameters));
                    parametersList.Add(parameters);
                }
            }
            if (referenceEntity != null)
            {
                DynamicParameters parameters = new DynamicParameters();
                sqls.Add(this.GetWorkflowActivityInstanceReferenceSql(referenceEntity, out parameters));
                parametersList.Add(parameters);
            }
            return sqls;
        }

        private string GetInsertAttendanceRemedyApplySql(AttendanceRemedyApplyEntity entity, out DynamicParameters parameters)
        {
            string sql = SqlCommands.GetInsertSql("OA_AttendanceRemedyApply", new string[] { "ApplyCode", "RemedyDate", "RemedyTime", "RemedyReason", "RemarkFiles", "ClassId", "ClassName", "AdminId", "AdminName", "DepartmentId", "DepartmentName", "WeekDay", "AttendanceGroupId" });
            parameters = new DynamicParameters();
            parameters.Add("?ClassId", entity.ClassId, DbType.Int64);
            parameters.Add("?ClassName", entity.ClassName, DbType.AnsiString, size: 50);
            parameters.Add("?AttendanceGroupId", entity.AttendanceGroupId, DbType.Int64);
            parameters.Add("?DepartmentName", entity.DepartmentName, DbType.AnsiString, size: 50);
            parameters.Add("?DepartmentId", entity.DepartmentId, DbType.Int64);
            parameters.Add("?AdminId", entity.AdminId, DbType.Int64);
            parameters.Add("?AdminName", entity.AdminName, DbType.AnsiString, size: 50);
            parameters.Add("?ApplyCode", entity.ApplyCode, DbType.AnsiString, size: 50);
            parameters.Add("?WeekDay", entity.WeekDay, DbType.AnsiString, size: 50);
            parameters.Add("?RemedyTime", entity.RemedyTime, DbType.AnsiString, size: 100);
            parameters.Add("?RemedyDate", entity.RemedyDate, DbType.DateTime);
            parameters.Add("?RemedyReason", entity.RemedyReason, DbType.AnsiString, size: 1000);
            parameters.Add("?RemarkFiles", entity.RemarkFiles, DbType.AnsiString, size: 100);
            return sql;
        }


        /// <summary>
        /// 新增一条任务参与者记录
        /// </summary>
        /// <param name="receiver">参与人</param>
        /// <param name="parameters">参与信息</param>
        /// <returns></returns>
        private string GetInsertTaskReceiverRecordSql(TaskReceiverRecordEntity receiver, out DynamicParameters parameters)
        {
            string sql = SqlCommands.GetInsertSql("OA_TaskReceiverRecord", new string[] { "ReceiverAdminId", "ReceiverAdminFullName", "ReceiverRole", "TaskStep", "WorkflowActivityInstanceId" });
            parameters = new DynamicParameters();
            parameters.Add("?WorkflowActivityInstanceId", receiver.WorkflowActivityInstanceId, DbType.Int64);
            parameters.Add("?ReceiverAdminId", receiver.ReceiverAdminId, DbType.Int64);
            parameters.Add("?ReceiverAdminFullName", receiver.ReceiverAdminFullName, DbType.AnsiString, size: 20);
            parameters.Add("?ReceiverRole", receiver.ReceiverRole, DbType.AnsiString, size: 20);
            parameters.Add("?TaskStep", receiver.TaskStep, DbType.Int32);
            return sql;
        }

        /// <summary>
        /// 新增一条任务记录
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private string GetInsertTaskRecordSql(TaskRecordEntity entity, out DynamicParameters parameters)
        {
            string sql = SqlCommands.GetInsertSql("OA_TaskRecord", new string[] { "WorkflowActivityInstanceId","TaskRecordNo", "TaskCategory", "BusinessType", "BusinessTypeName", "HandleStatus","StartTime","TaskExecuterAdminId","TaskExecuterFullName","CompleteTime",
                "RelevantTaskRecordNo","CurrentlyStep"});
            parameters = new DynamicParameters();
            parameters.Add("?WorkflowActivityInstanceId", entity.WorkflowActivityInstanceId, DbType.Int64, size: 20);
            parameters.Add("?TaskRecordNo", entity.TaskRecordNo, DbType.AnsiString, size: 50);
            parameters.Add("?TaskCategory", entity.TaskCategory.ToString(), DbType.AnsiString);
            parameters.Add("?BusinessType", entity.BusinessType.ToString(), DbType.AnsiString, size: 150);
            parameters.Add("?BusinessTypeName", entity.BusinessTypeName, DbType.AnsiString, size: 50);
            parameters.Add("?HandleStatus", entity.HandleStatus.ToString(), DbType.AnsiString);
            parameters.Add("?RelevantTaskRecordNo", entity.RelevantTaskRecordNo, DbType.AnsiString, size: 50);
            parameters.Add("?StartTime", entity.StartTime, DbType.Date, size: 50);
            parameters.Add("?CompleteTime", entity.CompleteTime, DbType.DateTime);
            parameters.Add("?CurrentlyStep", entity.CurrentlyStep, DbType.Int32, size: 10);
            parameters.Add("?TaskExecuterAdminId", entity.TaskExecuterAdminId.HasValue ? entity.TaskExecuterAdminId.Value : (long?)null, DbType.Int64);
            parameters.Add("?TaskExecuterFullName", entity.TaskExecuterFullName, DbType.AnsiString, size: 20);
            return sql;
        }

        private string GetWorkflowActivityInstanceReferenceSql(WorkflowActivityInstanceReferenceEntity referenceEntity, out DynamicParameters parameters)
        {
            string sql = SqlCommands.GetInsertSql("OA_WorkflowActivityInstanceReference", new string[] { "WorkflowActivityInstanceReferenceNo", "WorkflowActivityInstanceId", "WorkflowType", "BusinessType", "ReferenceNo", "ReferenceType" });
            parameters = new DynamicParameters();
            parameters.Add("?WorkflowActivityInstanceReferenceNo", referenceEntity.WorkflowActivityInstanceReferenceNo, DbType.AnsiString, size: 50);
            parameters.Add("?WorkflowActivityInstanceId", referenceEntity.WorkflowActivityInstanceId, DbType.Int64, size: 20);
            parameters.Add("?WorkflowType", referenceEntity.WorkflowType, DbType.AnsiString, size: 50);
            parameters.Add("?BusinessType", referenceEntity.BusinessType, DbType.AnsiString, size: 50);
            parameters.Add("?ReferenceNo", referenceEntity.ReferenceNo, DbType.AnsiString, size: 50);
            parameters.Add("?ReferenceType", referenceEntity.ReferenceType, DbType.AnsiString, size: 100);
            return sql;
        }

        public async Task<TaskRecordEntity> GetByTaskRecordNo(string taskRecordNo)
        {
            string sql = string.Format("{0} Where TaskRecordNo=?TaskRecordNo", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?TaskRecordNo", taskRecordNo.Trim(), DbType.AnsiString, size: 50);
            return await this.databaseContext.Slave.QueryFirstOrDefaultAsync<TaskRecordEntity>(sql, parameters);
        }

        public async Task<bool> Close(string taskRecordNo)
        {
            string sql = SqlCommands.GetUpdateSql("OA_TaskRecord", new string[] { "HandleStatus" }, new string[] { "TaskRecordNo" });
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?TaskRecordNo", taskRecordNo, DbType.AnsiString, size: 50);
            parameters.Add("?HandleStatus", OATaskHandleStatus.Closed.ToString(), DbType.Int64, size: 20);
            return await this.databaseContext.Master.ExecuteAsync(sql, parameters, databaseContext.Transaction) > 0;
        }


        public async Task<bool> Pass(string taskRecordNo)
        {
            string sql = SqlCommands.GetUpdateSql("OA_TaskRecord", new string[] { "HandleStatus", "CompleteTime" }, new string[] { "TaskRecordNo" });
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?TaskRecordNo", taskRecordNo, DbType.AnsiString, size: 50);
            parameters.Add("?HandleStatus", OATaskHandleStatus.Handled.ToString(), DbType.AnsiString, size: 20);
            parameters.Add("?CompleteTime", DateTime.Now, DbType.DateTime);
            return await this.databaseContext.Master.ExecuteAsync(sql, parameters, databaseContext.Transaction) > 0;
        }

        public async Task<bool> Paused(string taskRecordNo, string pauseRemark)
        {
            string sql = SqlCommands.GetUpdateSql("OA_TaskRecord", new string[] { "HandleStatus", "PauseTime", "PauseRemark" }, new string[] { "TaskRecordNo" });
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?TaskRecordNo", taskRecordNo, DbType.AnsiString, size: 50);
            parameters.Add("?PauseTime", DateTime.Now, DbType.DateTime);
            parameters.Add("?HandleStatus", OATaskHandleStatus.Paused.ToString(), DbType.Int64);
            parameters.Add("?PauseRemark", pauseRemark, DbType.AnsiString);
            return await this.databaseContext.Master.ExecuteAsync(sql, parameters, databaseContext.Transaction) > 0;
        }

        public async Task<bool> Reject(string taskRecordNo, TaskRejectRecordEntity entity)
        {
            List<string> sqls = new List<string>();
            List<DynamicParameters> parametersList = new List<DynamicParameters>();
            string sql = SqlCommands.GetUpdateSql("OA_TaskRecord", new string[] { "HandleStatus" }, new string[] { "TaskRecordNo" });
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?TaskRecordNo", taskRecordNo, DbType.AnsiString, size: 50);
            parameters.Add("?HandleStatus", OATaskHandleStatus.Rejected.ToString(), DbType.Int64, size: 20);
            sqls.Add(sql);
            parametersList.Add(parameters);
            sqls.Add(this.GetInserTaskRejectRecordSql(entity, out DynamicParameters parameters1));
            parametersList.Add(parameters1);
            int result = this.databaseContext.Master.TransactionExecuteAsync(sqls, parametersList, databaseContext.Transaction).GetAwaiter().GetResult();
            if (result > 0)
            {
                return true;
            }

            return await this.databaseContext.Master.ExecuteAsync(sql, parameters, databaseContext.Transaction) > 0;
        }

        private string GetInserTaskRejectRecordSql(TaskRejectRecordEntity entity, out DynamicParameters parameters)
        {
            string sql = SqlCommands.GetInsertSql("OA_TaskRejectRecord", new string[] { "TaskRecordNo", "RejectRemark", "RejectAdminId", "RejectAdminFullName", "RejectReceiverAdminId", "RejectReceiverAdminFullName", "WorkflowActivityInstanceId" });
            parameters = new DynamicParameters();
            parameters.Add("?TaskRecordNo", entity.TaskRecordNo, DbType.AnsiString, size: 50);
            parameters.Add("?RejectRemark", entity.RejectRemark, DbType.AnsiString, size: 50);
            parameters.Add("?RejectAdminId", entity.RejectAdminId, DbType.Int64);
            parameters.Add("?RejectAdminFullName", entity.RejectAdminFullName, DbType.AnsiString, size: 50);
            parameters.Add("?RejectReceiverAdminId", entity.RejectReceiverAdminId, DbType.Int64);
            parameters.Add("?WorkflowActivityInstanceId", entity.WorkflowActivityInstanceId, DbType.Int64);
            return sql;
        }

        public async Task<TaskRecordEntity> GetByTaskStepAndWorkflowActivityInstanceId(long workflowActivityInstanceId, int currentlyStep)
        {
            string sql = string.Format("{0} Where workflowActivityInstanceId=?workflowActivityInstanceId AND CurrentlyStep=?CurrentlyStep", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?workflowActivityInstanceId", workflowActivityInstanceId, DbType.Int64);
            parameters.Add("?CurrentlyStep", currentlyStep, DbType.Int64);
            return await this.databaseContext.Slave.QueryFirstOrDefaultAsync<TaskRecordEntity>(sql, parameters);
        }

        /// <summary>
        /// 根据关联业务单号和执行人查询任务信息
        /// </summary>
        /// <param name="referenceNo">关联业务单号</param>
        /// <param name="adminId">执行任务人</param>
        /// <returns></returns>
        public async Task<TaskRecordEntity> GetByReferenceNoAndTaskExecuterAdminId(string referenceNo, long adminId)
        {
            string sqlJoin = @"Select C.TaskRecordNo,C.BusinessTypeName,C.BusinessType,C.WorkflowActivityInstanceId,C.TaskCategory,C.HandleStatus,C.PauseTime,C.PauseRemark,C.RelevantTaskRecordNo,C.CurrentlyStep,C.CreateTime,C.TaskExecuterAdminId,
                    C.TaskExecuterFullName,C.StartTime,C.CompleteTime  from OA_workflowActivityInstanceReference A
                    LEFT JOIN  OA_WorkflowActivityInstance B ON A.WorkflowActivityInstanceId=B.WorkflowActivityInstanceId
                    LEFT JOIN  OA_TaskRecord C ON C.WorkflowActivityInstanceId=B.WorkflowActivityInstanceId AND B.CurrentlyStep=C.CurrentlyStep ";
            string sql = string.Format("{0} Where A.ReferenceNo=?ReferenceNo AND C.TaskExecuterAdminId=?TaskExecuterAdminId", sqlJoin);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?ReferenceNo", referenceNo.ToString(), DbType.AnsiString);
            parameters.Add("?TaskExecuterAdminId", adminId, DbType.Int64);
            return await this.databaseContext.Slave.QueryFirstOrDefaultAsync<TaskRecordEntity>(sql, parameters);
        }

      
        /// <summary>
        /// 新增条任务信息
        /// </summary>
        /// <param name="taskRecordEntity"></param>
        /// <returns></returns>
        public async Task<TaskRecordEntity> InsertAsync(TaskRecordEntity taskRecordEntity, List<TaskReceiverRecordEntity> receiverEntities)
        {
            List<string> sqls = new List<string>();
            List<DynamicParameters> parametersList = new List<DynamicParameters>();
            DynamicParameters parameters = new DynamicParameters();
            sqls.Add(this.GetInsertTaskRecordSql(taskRecordEntity, out parameters));
            parametersList.Add(parameters);
            if (receiverEntities != null && receiverEntities.Any())
            {
                foreach (var receiver in receiverEntities)
                {
                    DynamicParameters parameters1 = new DynamicParameters();
                    sqls.Add(this.GetInsertTaskReceiverRecordSql(receiver, out parameters1));
                    parametersList.Add(parameters1);
                }
            }
            int result = this.databaseContext.Master.TransactionExecuteAsync(sqls, parametersList, databaseContext.Transaction).GetAwaiter().GetResult();
            if (result > 0)
            {
                string sql = string.Format("{0} Where  TaskRecordNo=?TaskRecordNo", QUERY);
                DynamicParameters parameter = new DynamicParameters();
                parameters.Add("?TaskRecordNo", taskRecordEntity.TaskRecordNo.Trim(), DbType.AnsiString, size: 50);
                return await this.databaseContext.Master.QueryFirstOrDefaultAsync<TaskRecordEntity>(sql, parameter);
            }
            return new TaskRecordEntity();
        }

        public Task<bool> UpdateHandleStatusAsync(string taskRecordNo, OATaskHandleStatus taskHandleStatus)
        {
            throw new NotImplementedException();
        }
    }
}
